home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / xpalette.pro < prev    next >
Text File  |  1997-07-08  |  16KB  |  522 lines

  1. ; $Id: xpalette.pro,v 1.11 1997/03/11 01:58:13 griz Exp $
  2. ;
  3. ; Copyright (c) 1992-1997, Research Systems, Inc.  All rights reserved.
  4. ;       Unauthorized reproduction prohibited.
  5. ;+
  6. ; NAME:
  7. ;       XPALETTE
  8. ;
  9. ; PURPOSE:
  10. ;       Interactively create color tables using the RGB, CMY, HSV, and
  11. ;       HLS color systems using the mouse, three sliders, and a cell
  12. ;       for each color index. Single colors can be defined or multiple
  13. ;       color indices between two endpoints can be interpolated.
  14. ;
  15. ; CATEGORY:
  16. ;       Color tables, widgets.
  17. ;
  18. ; CALLING SEQUENCE:
  19. ;       XPALETTE
  20. ;
  21. ; INPUTS:
  22. ;       No explicit inputs.  The current color table is used as a starting
  23. ;       point.
  24. ;
  25. ; KEYWORD PARAMETERS:
  26. ;       None.
  27. ;
  28. ; OUTPUTS:
  29. ;       None.
  30. ;
  31. ; COMMON BLOCKS:
  32. ;       COLORS: Contains the current RGB color tables.
  33. ;       XP_COM: Private to this module.
  34. ;
  35. ; SIDE EFFECTS:
  36. ;       XPALETTE uses two colors from the current color table as
  37. ;       drawing foreground and background colors. These are used
  38. ;       for the RGB plots on the left, and the current index marker on
  39. ;       the right. This means that if the user set these two colors
  40. ;       to the same value, the XPALETTE display could become unreadable
  41. ;       (like writing on black paper with black ink). XPALETTE minimizes
  42. ;       this possibility by noting changes to the color map and always
  43. ;       using the brightest available color for the foreground color
  44. ;       and the darkest for the background. Thus, the only way
  45. ;       to make XPALETTE's display unreadable is to set the entire color
  46. ;       map to a single color, which is highly unlikely. The only side
  47. ;       effect of this policy is that you may notice XPALETTE redrawing
  48. ;       the entire display after you've modified the current color.
  49. ;       This simply means that the change has made XPALETTE pick new
  50. ;       drawing colors.
  51. ;
  52. ;       The new color tables are saved in the COLORS common and loaded
  53. ;       to the display.
  54. ;
  55. ; PROCEDURE:
  56. ;       The XPALETTE widget has the following controls:
  57. ;
  58. ;       Left:   Three plots showing the current Red, Green, and Blue vectors.
  59. ;
  60. ;       Center: A status region containing:
  61. ;               1) The total number of colors.
  62. ;               2) The current color. XPALETTE allows changing
  63. ;                  one color at a time. This color is known as
  64. ;                  the "current color" and is indicated in the
  65. ;                  color spectrum display with a special marker.
  66. ;               3) The current mark index. The mark is used to
  67. ;                  remember a color index. It is established by
  68. ;                  pressing the "Set Mark Button" while the current
  69. ;                  color index is the desired mark index.
  70. ;               4) The current color. The special marker used in
  71. ;                  color spectrum display prevents the user from seeing
  72. ;                  the color of the current index, but it is visible
  73. ;                  here.
  74. ;
  75. ;               A panel of control buttons, which do the following when
  76. ;               pressed:
  77. ;
  78. ;               Done:   Exits XPALETTE.
  79. ;
  80. ;         Predefined:   Starts XLOADCT to allow selection of one of the
  81. ;                       predefined color tables. Note that when you change
  82. ;                       the color map via XLOADCT, XPALETTE is not always
  83. ;                       able to keep its display accurate.  This problem can
  84. ;                       be overcome by pressing the XPALETTE "Redraw" button
  85. ;                       after changing things via XLOADCT.
  86. ;
  87. ;               Help:   Supplies help information similar to this header.
  88. ;
  89. ;               Redraw: Completely redraws the display using the current
  90. ;                       state of the color map.
  91. ;
  92. ;             Set Mark: Set the value of the mark index to the
  93. ;                       current index.
  94. ;
  95. ;          Switch Mark: Exchange the mark and the current index.
  96. ;
  97. ;         Copy Current: Every color lying between the current
  98. ;                       index and the mark index (inclusive) is given
  99. ;                       the current color.
  100. ;
  101. ;          Interpolate: The colors lying between the current
  102. ;                       index and the mark index are interpolated linearly
  103. ;                       to lie between the colors of two endpoints.
  104. ;
  105. ;       Three sliders (R, G, and B) that allow the user to modify the
  106. ;       current color.
  107. ;
  108. ;       Right:  A display which shows the current color map as a series of
  109. ;               squares. Color index 0 is at the upper left. The color index
  110. ;               increases monotonically by rows going left to right and top
  111. ;               to bottom.  The current color index is indicated by a special
  112. ;               marker symbol. There are 4 ways to change the current color:
  113. ;                       1) Press any mouse button while the mouse
  114. ;                          pointer is over the color map display.
  115. ;                       2) Use the "By Index" slider to move to
  116. ;                          the desired color index.
  117. ;                       3) Use the "Row" Slider to move the marker
  118. ;                          vertically.
  119. ;                       4) Use the "Column" Slider to move the marker
  120. ;                          horizontally.
  121. ;
  122. ; MODIFICATION HISTORY:
  123. ;       July 1990, AB.          Based on the PALETTE procedure, which does
  124. ;                               similar things using only basic IDL graphics
  125. ;                               commands.
  126. ;
  127. ;       7 January 1991, Re-written for general use.
  128. ;       1 April 1992, Modified to use the CW_RGBSLIDER and CW_COLORSEL
  129. ;               compound widgets. The use of color systems other than
  130. ;               RGB is now supported.
  131. ;       15 June 1992, Modified to use the CW_FIELD and CW_BGROUP compound
  132. ;               widgets.
  133. ;       7 April 1993, Removed state caching. Fixed a bug where switching
  134. ;        the current index and the mark would fail to update the
  135. ;        current index label.
  136. ;       10 March 1997, Added !X.TYPE and !Y.TYPE to saved state.
  137. ;-
  138.  
  139. function XP_NEW_COLORS
  140. ; Choose the best foreground and background colors for the current
  141. ; color maps and set !P appropriately. Returns 1 if the colors changed,
  142. ; 0 otherwise.
  143.   common xp_com, xpw, state
  144.  
  145.   res = 0
  146.   junk = CT_LUMINANCE(dark=dark_col, bright=bright_col)
  147.  
  148.   if (bright_col ne !p.color) then begin
  149.     !p.color = bright_col
  150.     res = 1
  151.   endif
  152.  
  153.   if (dark_col ne !p.background) then begin
  154.     !p.background = dark_col
  155.     res = 1
  156.   endif
  157.  
  158.   return, res
  159. end
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167. pro XP_REPLOT, color_index, type
  168. ; Re-draw the RGB plots. Type has the following possible values.
  169. ;;      - 'D': Draw the data part of all three plots
  170. ;       - 'F': draw all three plots
  171. ;       - 'R': Draw the data part of the Red plot
  172. ;       - 'G': Draw the data part of the Green plot
  173. ;       - 'B': Draw the data part of the Blue plot
  174.  
  175.   common xp_com, xpw, state
  176.   common colors, r_orig, g_orig, b_orig, r_curr, g_curr, b_curr
  177.   common pscale, r_x_s, r_y_s, g_x_s, g_y_s, b_x_s, b_y_s
  178.  
  179.   ; Update the plots of RGB
  180.   save_win = !D.WINDOW
  181.   wset, state.plot_win
  182.   save_p_region = !p.region
  183.   save_x_margin = !x.margin
  184.   save_y_margin = !y.margin
  185.   save_x_s = !x.s
  186.   save_y_s = !y.s
  187.   save_x_type = !x.type 
  188.   save_y_type = !y.type 
  189.  
  190.   !y.margin= [2, 2]
  191.   !x.margin= [6, 2]
  192.  
  193.   if (type eq 'F') then begin
  194.     !p.region = [0,.6667, 1, 1]
  195.     plot,xstyle=2, ystyle=3, yrange=[0, 260], r_curr, title='Red'
  196.     r_x_s = !x.s
  197.     r_y_s = !y.s
  198.  
  199.     !p.region = [0,.333, 1, .6667]
  200.     plot,/noerase, xstyle=2,ystyle=3, yrange=[0, 260], g_curr, title='Green'
  201.     g_x_s = !x.s
  202.     g_y_s = !y.s
  203.  
  204.     !p.region = [0,0, 1, .333]
  205.     plot,/noerase, xstyle=2,ystyle=3, yrange=[0, 260], b_curr, title='Blue'
  206.     b_x_s = !x.s
  207.     b_y_s = !y.s
  208.   endif else begin
  209.     if ((type eq 'D') or (type eq 'R')) then begin
  210.       !p.region = [0,.6667, 1, 1]
  211.       !x.s = r_x_s
  212.       !y.s = r_y_s
  213.       oplot, r_curr, color=color_index
  214.     endif
  215.     if ((type eq 'D') or (type eq 'G')) then begin
  216.       !p.region = [0,.333, 1, .6667]
  217.       !x.s = g_x_s
  218.       !y.s = g_y_s
  219.       oplot, g_curr, color=color_index
  220.     endif
  221.     if ((type eq 'D') or (type eq 'B')) then begin
  222.       !p.region = [0,0, 1, .333]
  223.       !x.s = b_x_s
  224.       !y.s = b_y_s
  225.       oplot, b_curr, color=color_index
  226.     endif
  227.   endelse
  228.  
  229.   WSET, save_win
  230.   !p.region = save_p_region
  231.   !x.margin = save_x_margin
  232.   !y.margin = save_y_margin
  233.   !x.s = save_x_s
  234.   !y.s = save_y_s
  235.   !x.type = save_x_type
  236.   !y.type = save_y_type
  237.  
  238. end
  239.  
  240.  
  241.  
  242.  
  243. pro XP_CHANGE_COLOR, type, value
  244. ; Change current color. Type has the following possible values.
  245. ;       - 'R': Change the R part of the current color
  246. ;       - 'G': ...
  247. ;       - 'B': ...
  248.   common xp_com, xpw, state
  249.   common colors, r_orig, g_orig, b_orig, r_curr, g_curr, b_curr
  250.  
  251.  
  252.   cur_idx = state.cur_idx
  253.  
  254.   XP_REPLOT, !p.background, type
  255.  
  256.   if (type eq 'R') then r_curr[cur_idx] = value;
  257.   if (type eq 'G') then g_curr[cur_idx] = value;
  258.   if (type eq 'B') then b_curr[cur_idx] = value;
  259.  
  260.   tvlct, r_curr[cur_idx], g_curr[cur_idx], b_curr[cur_idx], cur_idx
  261.  
  262.   if (XP_NEW_COLORS()) then begin
  263.     ; Highlight the current position using the marker
  264.     WIDGET_CONTROL, xpw.colorsel, set_value=-1  ; Re-initialize
  265.     XP_REPLOT, !p.color, 'F'
  266.   endif else begin
  267.     XP_REPLOT, !p.color, type
  268.   endelse
  269.  
  270. end
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278. pro XP_BUTTON_EVENT, event
  279.  
  280.   common xp_com, xpw, state
  281.   common colors, r_orig, g_orig, b_orig, r_curr, g_curr, b_curr
  282.  
  283.   ; NOTE: The value of these tags depend on the order of the buttons
  284.   ;     in the base.
  285.   case (event.value) of
  286.  
  287.     ; DONE
  288.     0: begin
  289.     empty
  290.  
  291.     ;WRITE_MASKS not valid for MS Windows
  292.     IF (!VERSION.OS NE 'Win32') AND (!VERSION.OS NE 'MacOS') THEN $
  293.         device,set_write=state.old_mask         ;Restore old write mask
  294.     r_orig = r_curr & g_orig = g_curr & b_orig = b_curr ;new orig color tbl
  295.     WIDGET_CONTROL, /DESTROY, event.top
  296.     !p = state.old_p
  297.       end
  298.  
  299.     ; PREDEFINED
  300.     1: xloadct, /silent, group=xpw.base
  301.  
  302.     ; HELP
  303.     2: XDisplayFile, FILEPATH("xpalette.txt", subdir=['help', 'widget']), $
  304.     TITLE = "XPalette Help", GROUP = event.top, WIDTH = 55, HEIGHT = 16
  305.  
  306.     ; REDRAW
  307.     3: begin
  308.     junk = XP_NEW_COLORS()
  309.     WIDGET_CONTROL, xpw.colorsel, set_value=-1
  310.     XP_REPLOT, !p.color, 'F'        ; Update the plots of RGB
  311.     end
  312.  
  313.     ; SET MARK
  314.     4: begin
  315.       state.mark_idx = state.cur_idx
  316.       WIDGET_CONTROL, xpw.mark_label, $
  317.           set_value=strcompress(state.mark_idx, /REMOVE)
  318.     endif
  319.  
  320.     ; SWITCH MARK
  321.     5 : if (state.mark_idx ne state.cur_idx) then begin
  322.       tmp = state.mark_idx
  323.       state.mark_idx = state.cur_idx
  324.       state.cur_idx = tmp
  325.       WIDGET_CONTROL, xpw.colorsel, set_value=tmp
  326.       WIDGET_CONTROL, xpw.idx_label, $
  327.             set_value=strcompress(state.cur_idx, /REMOVE)
  328.       WIDGET_CONTROL, xpw.mark_label, $
  329.             set_value=strcompress(state.mark_idx, /REMOVE)
  330.       endif
  331.  
  332.     ; COPY CURRENT
  333.     6 : begin
  334.       do_copy:
  335.     cur_idx = state.cur_idx
  336.     if (state.mark_idx le cur_idx) then begin
  337.       s = state.mark_idx
  338.       e = cur_idx
  339.     endif else begin
  340.       s = cur_idx
  341.       e = state.mark_idx
  342.     endelse
  343.     n = e-s+1
  344.     XP_REPLOT, !p.background, 'D'
  345.     if (event.value eq 6) then begin
  346.       r_curr[s:e] = r_curr[cur_idx]
  347.       g_curr[s:e] = g_curr[cur_idx]
  348.       b_curr[s:e] = b_curr[cur_idx]
  349.     endif else begin                        ; Interpolate
  350.       scale = findgen(n)/float(n-1)
  351.       r_curr[s:e] = r_curr[s] + (fix(r_curr[e]) - fix(r_curr[s])) * scale
  352.       g_curr[s:e] = g_curr[s] + (fix(g_curr[e]) - fix(g_curr[s])) * scale
  353.       b_curr[s:e] = b_curr[s] + (fix(b_curr[e]) - fix(b_curr[s])) * scale
  354.     endelse
  355.     tvlct, r_curr[s:e], g_curr[s:e], b_curr[s:e], s
  356.     if (XP_NEW_COLORS()) then begin
  357.       WIDGET_CONTROL, xpw.colorsel, SET_VALUE=-1
  358.       XP_REPLOT, !p.color, 'F'
  359.     endif else begin
  360.       XP_REPLOT, !p.color, 'D'
  361.     endelse
  362.     end
  363.  
  364.     7: goto, do_copy
  365.     else:
  366.   endcase
  367.  
  368. end
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376. pro XP_EVENT, event
  377.  
  378.   common xp_com, xpw, state
  379.   common colors, r_orig, g_orig, b_orig, r_curr, g_curr, b_curr
  380.  
  381.   case (event.id) of
  382.  
  383.   xpw.button_base: XP_BUTTON_EVENT, event
  384.  
  385.   xpw.rgb_base: begin
  386.     cur_idx = state.cur_idx
  387.     if (event.r ne r_curr[cur_idx]) then XP_CHANGE_COLOR, "R", event.r
  388.     if (event.g ne g_curr[cur_idx]) then XP_CHANGE_COLOR, "G", event.g
  389.     if (event.b ne b_curr[cur_idx]) then XP_CHANGE_COLOR, "B", event.b
  390.     end
  391.  
  392.   xpw.colorsel: begin
  393.     cur_idx = state.cur_idx
  394.     new_pos = event.value ne cur_idx
  395.     ; Update the RBG sliders
  396.     if (event.value ne cur_idx) then begin
  397.       state.cur_idx = (cur_idx = event.value)
  398.       WIDGET_CONTROL, xpw.idx_label,  $
  399.               set_value=strcompress(cur_idx, /REMOVE_ALL)
  400.       ; Mark new square
  401.       tmp = !D.WINDOW
  402.       wset, state.cur_color_win
  403.       erase, color=cur_idx
  404.           wset, tmp
  405.  
  406.       WIDGET_CONTROL, xpw.rgb_base, $
  407.           set_value=[r_curr[cur_idx], g_curr[cur_idx], b_curr[cur_idx]]
  408.       endif
  409.     end
  410.  
  411.     else:
  412.     endcase
  413.  
  414. end
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.  
  422. pro XPALETTE, group=group
  423.  
  424.   common xp_com, xpw, state
  425.   common colors, r_orig, g_orig, b_orig, r_curr, g_curr, b_curr
  426.  
  427.   xpw = { xp_widgets, base:0L,  $
  428.     colorsel:0L, mark_label:0L, idx_label:0L, button_base:0L, rgb_base:0L}
  429.  
  430.   state = {old_mask:0L, $               ; Original mask
  431.        old_p:!p, $                  ; Original value of !P
  432.        mark_idx:0, $                ; Current mark index
  433.        cur_idx:0, $                 ; Current index
  434.        cur_color_win:0, $           ; Current Color draw window index
  435.        plot_win:0 }                 ; RGB plot draw window index
  436.  
  437.   if (XREGISTERED('XPALETTE')) then return      ; Only one copy at a time
  438.  
  439.   on_error,2              ;Return to caller if an error occurs
  440.  
  441.   ;WRITE_MASKS not valid for MS Windows
  442.   IF (!VERSION.OS NE 'Win32') AND (!VERSION.OS NE 'MacOS') THEN $
  443.     device,get_write=tmp,set_write=255  ELSE $ ;Enable all bits
  444.     tmp = 0
  445.  
  446.   state.old_mask=tmp
  447.  
  448.   nc = !d.table_size            ;# of colors avail
  449.   if nc eq 0 then message, "Device has static color tables.  Can't modify."
  450.   if (nc eq 2) then message, 'Unable to work with monochrome system.'
  451.  
  452.   state.old_p = !p              ;Save !p
  453.   !p.noclip = 1                 ;No clipping
  454.   !p.color = nc -1              ;Foreground color
  455.   !p.font = 0                   ;Hdw font
  456.   save_win = !d.window  ;Previous window
  457.  
  458.   IF N_ELEMENTS(r_orig) LE 0 THEN BEGIN    ;If no common, use current colors
  459.     TVLCT, r_orig, g_orig, b_orig, /GET
  460.     r_curr = r_orig
  461.     b_curr = b_orig
  462.     g_curr = g_orig
  463.     ENDIF
  464.  
  465.   ; Create widgets
  466.   xpw.base=WIDGET_BASE(title='XPalette', /ROW, space=30)
  467.   ; This is a little tricky. Setting the managed attribute indicates
  468.   ; our intention to put this app under the control of XMANAGER, and
  469.   ; prevents our draw widgets from becoming candidates for becoming
  470.   ; the default window on WSET, -1. XMANAGER sets this, but doing it here
  471.   ; prevents our own WSETs at startup from having that problem.
  472.   WIDGET_CONTROL, /MANAGED, xpw.base
  473.  
  474.   version = WIDGET_INFO(/VERSION)
  475.   if (version.style='Motif') then junk=510 else junk = 580
  476.   plot_frame = WIDGET_DRAW(xpw.base, xsize=200, ysize=junk)
  477.  
  478.   c1 = WIDGET_BASE(xpw.base, /COLUMN, space=20)
  479.     status = WIDGET_BASE(c1, /COLUMN, /FRAME)
  480.       ncw = WIDGET_LABEL(WIDGET_BASE(status), /DYNAMIC_RESIZE)
  481.       xpw.idx_label = CW_FIELD(status, title='Current Index: ', value='0', $
  482.                    xsize=20, /STRING)
  483.       xpw.mark_label = CW_FIELD(status, title='Mark Index:    ', value='0', $
  484.                 xsize=20, /STRING)
  485.       c1_1 = widget_base(status, /ROW)
  486.     junk = WIDGET_LABEL(c1_1, value="Current Color: ")
  487.       cur_color = WIDGET_DRAW(c1_1, xsize = 125, ysize=50, /frame)
  488.     names = [ 'Done', 'Predefined', 'Help', 'Redraw', 'Set Mark', $
  489.         'Switch Mark', 'Copy Current', 'Interpolate' ]
  490.     xpw.button_base = CW_BGROUP(c1, names, COLUMN=3, /FRAME)
  491.     xpw.rgb_base = CW_RGBSLIDER(c1, /FRAME, /DRAG)
  492.  
  493.     junk = WIDGET_BASE(xpw.base)        ; Responds to YOFFSET
  494.     if (version.style='Motif') then junk2=30 else junk2 = 50
  495.     xpw.colorsel = CW_COLORSEL(junk, yoffset=junk2)
  496.  
  497.  
  498.   state.cur_idx = 0
  499.   state.mark_idx = 0
  500.  
  501.   ; Position RGB slider appropriately
  502.   WIDGET_CONTROL, xpw.rgb_base, SET_VALUE=[r_curr[0], g_curr[0], b_curr[0]]
  503.   WIDGET_CONTROL, /REALIZE, xpw.base
  504.  
  505.   WIDGET_CONTROL, ncw, $
  506.     set_value='Number Of Colors: ' + strcompress(!d.n_colors, /REMOVE_ALL)
  507.   WIDGET_CONTROL, get_value=tmp, cur_color
  508.   state.cur_color_win = tmp
  509.   WIDGET_CONTROL, get_value=tmp, plot_frame
  510.   state.plot_win = tmp
  511.  
  512.  
  513.   ; Update the plots of RGB
  514.   junk = XP_NEW_COLORS()
  515.   XP_REPLOT, !p.color, 'F'
  516.  
  517.   WSET, save_win
  518.  
  519.   XMANAGER, 'XPalette', xpw.base, event_handler='XP_EVENT', group=group, $
  520.     /NO_BLOCK
  521. end
  522.